package com.ruoyi.message.general.base;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * @author liyang
 * @apiNote
 * @date 2021-08-16 15:17:34
 */
public abstract class AbstractCrudService<E> implements BaseCrudService<E> {

    @Autowired
    protected RedissonClient redissonClient;

    /**
     * 获得具体实现BaseMapper
     *
     * @return
     */
    protected abstract BaseMapper<E> getMapper();

    @Override
    public E getById(Long id) {
        return getMapper().selectById(id);
    }

    @Override
    public Long count(Wrapper<E> wrapper) {
        return getMapper().selectCount(wrapper);
    }

    @Override
    public List<E> getByIds(Long[] ids) {
        return getMapper().selectBatchIds(Arrays.asList(ids));
    }

    @Override
    public List<E> getByList(E e, String... columns) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>(e);
        if (columns != null && columns.length > 0) {
            queryWrapper.select(columns);
        }
        return getMapper().selectList(queryWrapper);
    }

    @Override
    public List<E> getByList(Wrapper<E> wrapper) {
        return getMapper().selectList(wrapper);
    }

    @Override
    public Page<E> getByPage(Page<E> page, E e, String... columns) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>(e);
        if (columns != null && columns.length > 0) {
            queryWrapper.select(columns);
        }
        return getMapper().selectPage(page, queryWrapper);
    }

    @Override
    public Page<E> getByPage(Page<E> page, Wrapper<E> wrapper) {
        return getMapper().selectPage(page, wrapper);
    }

    @Override
    public E getByObj(Wrapper<E> wrapper) {
        return getMapper().selectOne(wrapper);
    }

    @Override
    public E getByObj(E e) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>(e);
        return getMapper().selectOne(queryWrapper);
    }

    @Override
    @Transactional
    public E save(E e) {
        RLock lock = redissonClient.getLock(this.getClass().getSimpleName() + "Save");
        try {
            lock.lock();
            getMapper().insert(e);
        } catch (Exception ex) {
            throw ex;
        } finally {
            if (lock.isHeldByCurrentThread() && lock.isLocked()) {
                lock.unlock();
            }
        }
        return e;
    }

    @Override
    @Transactional
    public int update(E e) {
        RLock lock = redissonClient.getLock(this.getClass().getSimpleName() + "Update");
        int row = 0;
        try {
            lock.lock();
            row = getMapper().updateById(e);
        } catch (Exception ex) {
            throw ex;
        } finally {
            if (lock.isHeldByCurrentThread() && lock.isLocked()) {
                lock.unlock();
            }
        }
        return row;
    }

    @Override
    @Transactional
    public int update(E e, Wrapper<E> uw) {
        RLock lock = redissonClient.getLock(this.getClass().getSimpleName() + "BatchUpdate");
        int row = 0;
        try {
            lock.lock();
            row = getMapper().update(e, uw);
        } catch (Exception ex) {
            throw ex;
        } finally {
            if (lock.isHeldByCurrentThread() && lock.isLocked()) {
                lock.unlock();
            }
        }
        return row;
    }

    @Override
    @Transactional
    public int delete(Long[] ids) {
        return getMapper().deleteBatchIds(Arrays.asList(ids));
    }

    @Override
    @Transactional
    public int delete(Wrapper<E> wrapper) {
        return getMapper().delete(wrapper);
    }

}
